package org.feit.findword.view;

import org.feit.findword.game.Game;

public class FingerTracker {
	private final static String TAG = "FingerTracker";

	private GameBoardView mGameView;
	private Game mGame;

	private int mNumTouched;
	private byte mTouched[];
	private long mTouchedBits;

	private byte mTouching;

	private int mLeft;
	private int mTop;
	private int mWidth;
	private int mHeight;
	private int mBoardWidth;

	private int mBoxWidth;
	private int mRadiusSquared;
	private String mCurrentWord;

	FingerTracker(GameBoardView view, Game game) {
		mGameView = view;
		mGame = game;
		mTouched = new byte[mGame.getBoard().getSize()];
		mTouchedBits = 0;
		mBoardWidth = mGame.getBoard().getWidth();
		reset();
	}

	private void reset() {
		// Log.d(TAG,"RESET");
		for (int i = 0; i < mTouched.length; i++) {
			mTouched[i] = -1;
		}

		if (mNumTouched > 0) {
			mGameView.mHighlighted = 0;
		}
		mTouchedBits = 0;
		mNumTouched = 0;
		mTouching = -1;
	}

	private void countTouch() {
		long touchBit = 1L << mTouching;
		if ((mTouchedBits & touchBit) > 0)
			return;

		mTouched[mNumTouched] = mTouching;
		mTouchedBits |= 1L << mTouching;
		mGameView.mHighlighted = mTouchedBits;
		mNumTouched++;
		mGameView.redraw();
		mGame.playTouchSound();
	}

	void touchScreen(int x, int y) {
		if (x < mLeft || x >= (mLeft + mWidth))
			return;
		if (y < mTop || y >= (mTop + mHeight))
			return;

		// Log.d(TAG,"Touching:"+x+","+y);

		int bx = (x - mLeft) * mBoardWidth / mWidth;
		int by = (y - mTop) * mBoardWidth / mHeight;

		touchBox(bx, by);

		if (canTouch(bx + mBoardWidth * by) && nearCenter(x, y, bx, by)) {
			countTouch();
		}
	}

	private boolean canTouch(int box) {
		long boxBits = 1L << box;
		mCurrentWord = getWord();
		if ((boxBits & mTouchedBits) > 0)
			return false;

		return (boxBits & mGame.getBoard()
				.transitions(mTouched[mNumTouched - 1])) > 0;
	}

	private void touchBox(int x, int y) {
		int box = x + mBoardWidth * y;
		//mKeyboardTracker.reset();

		// Log.d(TAG,"Box:"+x+","+y+"="+box);

		if (mTouching < 0) {
			mTouching = (byte) box;
			countTouch();
		} else if (mTouching != box && canTouch(box)) {
			mTouching = (byte) box;
		}

		// Log.d(TAG,"Touching:"+touching);
	}

	private boolean nearCenter(int x, int y, int bx, int by) {
		int cx, cy;

		cx = mLeft + bx * mBoxWidth + mBoxWidth / 2;
		cy = mTop + by * mBoxWidth + mBoxWidth / 2;

		int d_squared = (cx - x) * (cx - x) + (cy - y) * (cy - y);

		return d_squared < mRadiusSquared;
	}

	void boundBoard(int l, int t, int w, int h) {
		mLeft = l;
		mTop = t;
		mWidth = w;
		mHeight = h;

		mBoxWidth = mWidth / mBoardWidth;

		mRadiusSquared = mBoxWidth / 3;
		mRadiusSquared *= mRadiusSquared;
	}

	String getWord() {
		String ret = "";

		for (int i = 0; i < mNumTouched; i++) {
			ret += mGame.getBoard().elementAt(mTouched[i]).toUpperCase();
		}

		return ret;
	}

	void release() {
		if (mNumTouched > 0) {
			String s = getWord();

			mGame.addWord(s);
			mCurrentWord = null;
		}

		// Log.d(TAG,s);

		reset();
	}
	
	public String getCurrentWord() {
		return mCurrentWord;
	}
}
